<?php
/**
 * 解析参数 或者返回帮助列表
 */
namespace App\Command;

use App\Utility\Extend\Schema;
use Curl\Curl;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
 *
 */
class rest extends Command
{
    private $domain = "192.168.1.190"; // api域名 + 版本号

    protected function configure()
    {
        $this
        // configure an argument
        ->addArgument('moduleName', InputArgument::REQUIRED, 'The moduleName of the restApi.')
            ->addArgument('className', InputArgument::REQUIRED, 'The className of the restApi.')
            ->addArgument('modelName', InputArgument::REQUIRED, 'The modelName of the restApi.')
            ->addArgument('tableName', InputArgument::REQUIRED, 'The tableName of the mysql.')
        // ...
        ;

        // 选项
        $this->addOption('Description', 'd', InputOption::VALUE_REQUIRED, 'test'); //11111
        $this->addOption('Author', 'a', InputOption::VALUE_OPTIONAL, 'test'); //作者

        $this->setName('rest')->setDescription('create restFul API')->setHelp('You can create rest Api just one command...');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // 获取参数值
        $args = $input->getArguments();

        // 获取选项值
        $options = $input->getOptions();

        $Description = $options['Description'];

        $curdModel = file_get_contents('./Application/Utility/Tpl/CurdModel.tpl');
        $RestController = file_get_contents('./Application/Utility/Tpl/RestController.tpl');
        $CurdValidate = file_get_contents('./Application/Utility/Tpl/CurdValidate.tpl');

        $all = $args + $options;
        $all['tableNameHump'] = preg_replace_callback('/([-_]+([a-z]{1}))/i', function ($matches) {
            return strtoupper($matches[2]);
        }, $all['tableName']);

        $schema = new Schema();

        // 判断表是否已经建立  已经创建这里直接跳过
        $tableName = $args['tableName'];
        $tableExist = $schema->tableExist("SELECT table_name FROM information_schema.TABLES WHERE table_name ='$tableName'");
        if (!count($tableExist)) {
            // 如果存在同名sql 则读取创建表的 sql 并运行  否则提示用户创建相关sql文件
            if (is_file('./Application/Schema/' . $args['tableName'] . '.sql')) {
                // 运行这段sql语句 创建表
                $schema->createTable('./Application/Utility/Schema/' . $args['tableName'] . '.sql');
            } else {
                $output->writeln('Lack of SQL files; name: ' . $args['tableName'] . '.sql' . " position: Applacation/Schema/");die;
            }
        }

        $tableStruct = $schema->query("SHOW FULL FIELDS FROM " . $args['tableName']);

        $rule = '';
        $message = '';
        $params = [];
        $ListTable = '';
        $AddTable = '';
        $EditTable = '';
        $AddSelectData = [];
        $AddSelect = [];
        $uploadImg = [];
        $AddRules = [];
        foreach ($tableStruct as $k => $v) {
            $field = $v['Field'];
            $comment = $v['Comment'];
            $type = $v['Type'];

            if ($ListTable) {
                $ListTable .= "
     | {$field} | {$type} | {$comment} |";
            } else {
                $ListTable = "| {$field} | {$type} | {$comment} |";
            }

            if ($v['Key'] != "PRI" and $v['Default'] === null) {

                $tHeader[] = $comment;
                $filterVal[] = $field;

                // 页面提交必填项
                if (strpos($comment, '(单选)') !== false) { // 如果注释中使用 (单选)  标明  则该项为单选项
                    $AddSelect[] = ['prop' => $field, 'label' => $comment];
                    $AddSelectData[$field] = null;
                } else {
                    if (strpos($comment, '(图片)') !== false) { // 如果注释中使用 (图片)  标明  则该项为图片
                        $uploadImg = ['prop' => $field, 'label' => $comment];
                    } else {
                        $AddInput[] = ['prop' => $field, 'label' => $comment];
                    }
                    $AddForm[$field] = null;
                }

                // char 类型
                if (strpos($type, 'char') !== false) {
                    $AddRules[$field] = [['required' => true, 'message' => "请输入" . $comment]];
                    $params[$field] = 'this is ' . $field;
                }
                // int 类型
                if (strpos($type, 'int') !== false) {
                    $params[$field] = 1;
                }

                if ($AddTable) {
                    $AddTable .= "
        | {$field} | {$type} | 是 |{$comment} |";
                } else {
                    $AddTable = "| {$field} | {$type} | 是 | {$comment} |";
                }

                if ($EditTable) {
                    $EditTable .= "
    | {$field} | {$type} | 否 |{$comment} |";
                } else {
                    $EditTable = "| {$field} | {$type} | 否 | {$comment} |";
                }

                if ($rule) {
                    $rule .= "
         '$field'        => 'require',";
                    $message .= "
         '{$field}.require'    => '请输入{$comment}',";
                } else {
                    $rule = "'$field'        => 'require',";
                    $message = "'{$field}.require'    => '请输入{$comment}',";
                }
            }
        }

        // 待替换变量
        $all['tableNameHump'] = ucfirst($all['tableNameHump']);
        $all['date'] = date("Y-m-d H:i:s");
        $all['rule'] = $rule;
        $all['message'] = $message;
        if (empty($all['Author'])) {
            $all['Author'] = "orchief";
        }

        // 替换变量
        foreach ($all as $k => $v) {
            $waitReplace[] = '{{$' . $k . '}}';
            $replace[] = $v;
        }
        $RestController = str_replace($waitReplace, $replace, $RestController);
        $curdModel = str_replace($waitReplace, $replace, $curdModel);
        $CurdValidate = str_replace($waitReplace, $replace, $CurdValidate);

        // 判断模块是否存在 不存在则创建
        $moduleName = $args['moduleName'];
        $className = $args['className'];

        $dir = iconv("UTF-8", "GBK", '/Application/HttpController/' . $args['moduleName']);
        if (!file_exists('/Application/HttpController/' . $moduleName)) {
            mkdir('/Application/HttpController/' . $moduleName, 0775, true);
        }
       
        file_put_contents('/Application/HttpController/' . $moduleName . $className . '.php', $RestController);
        file_put_contents('/Application/Model/' . $args['modelName'] . '.php', $curdModel);
        file_put_contents('/Application/Validate/' . $all['tableNameHump'] . '.php', $CurdValidate);

        // 新增rest路由
        // $this -> genRoutes($args);

        $Description = iconv("GB2312", "UTF-8", $Description);

        $assigns = [
            'Description' => '描述信息',
            'moduleName' => $moduleName,
            'className' => $className,
        ];

        $assigns['ListTable'] = $ListTable;
        $assigns['AddTable'] = $AddTable;
        $assigns['EditTable'] = $EditTable;
        $assigns['IndexTable'] = $ListTable;
        // 对一个接口进行 基于restful风格的访问
        $assigns = $this->restQuery($moduleName . '/' . $className, $assigns, $params, $output);

        $this->modifyApiMd('./api.md', $assigns);

        // 自动生成权限和菜单数据
        $AddTitle = '新增' . $Description;
        // 编辑
        $EditForm = $AddForm;

        $EditSelectData = $AddSelectData;

        $EditTitle = '编辑' . $Description;

        $EditInput = $AddInput;

        $EditSelect = $AddSelect;

        $EditRules = [];

        // 列表配置
        $baseApi = $moduleName . '/' . $className;
        $configFileName = $Description . '列表';

        $width = [200, 200, 200, 200];

        $search_input = [
            [
                'name' => "field",
                'placeholder' => "fieldName",
            ],
        ];
        $search_select = [
            [
                'name' => "field",
                'placeholder' => "fieldName",
                'multiple' => false,
            ],
        ];
        $searchReceived = [
            'status' => [
                [
                    'label' => "启用",
                    'value' => "1",
                ],
                [
                    'label' => "禁用",
                    'value' => "0",
                ],
            ],
        ];

        $searchExchanged = [
            'limit' => 10,
            'page' => 1,
            'orderByString' => "",
        ];

        // 配置数组
        $configArr = [
            'Add' => [
                'dialogFormVisible' => false,
                'data' => [
                    'primary' => '',
                    'form' => $AddForm, // 新增字段
                    'selectData' => $AddSelectData, // 有备选项的字段
                ],
                'config' => [
                    'uploadUrl' => 'axios.defaults.baseURL + \'admin/upload\'',
                    'domain' => 'axios.defaults.baseURL',
                    'title' => $AddTitle, // 新增标题
                    'form' => [
                        'input' => $AddInput, // 新增文本项
                        'select' => $AddSelect, // 新增单选项
                        'uploadImg' => $uploadImg,
                    ],
                    'rules' => $AddRules, // 新增限制规则
                ],
            ],
            'Edit' => [
                'dialogFormVisible' => false,
                'data' => [
                    'primary' => '',
                    'form' => $EditForm, // 编辑字段
                    'selectData' => $EditSelectData, // 有备选项的字段
                ],
                'config' => [
                    'uploadUrl' => 'axios.defaults.baseURL + \'admin/upload\'',
                    'domain' => 'axios.defaults.baseURL',
                    'title' => $EditTitle, // 编辑标题
                    'form' => [
                        'input' => $EditInput, // 编辑文本项
                        'select' => $EditSelect, // 编辑单选项
                        'uploadImg' => $uploadImg,
                    ],
                    'rules' => $AddRules, // 编辑限制规则
                ],
            ],
            'config' => [
                'baseApi' => $baseApi,
                'excel' => [
                    'fileName' => $configFileName, // 导出的excel表格名称
                    'tHeader' => $tHeader, // 表头
                    'filterVal' => $filterVal, // 字段名
                ],
                'table' => [
                    'noGroup' => true,
                    'checkbox' => false,
                    'status' => false,
                    'sort' => [
                        'field' => "custom",
                    ],
                    'show' => [
                        'items' => $tHeader,
                        'prop' => $filterVal,
                        'width' => $width,
                    ],
                    'operate' => [
                        'del' => true,
                        'edit' => true,
                    ],
                ],
                'search' => [
                    'search_input' => $search_input,
                    'search_select' => [

                    ],
                ],
                'page' => [
                    'limits' => [5, 10, 20, 50, 100],
                    'layout' => "total, sizes, prev, pager, next, jumper",
                ],
            ],
            'data' => [
                'received' => [
                    'table' => [],
                    'count' => null,
                    'search' => $searchReceived,
                ],
                'exchanged' => [
                    'search' => $searchExchanged,
                    'multipleSelection' => [],
                    'isDelete' => 0,
                ],
            ],
        ];

        // json格式的配置文件
        $configJson = json_encode($configArr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

        file_put_contents($args['className'] . '.json', $configJson);

        exec("mv ".$args['className'].".json  ./Application/Utility/VueConfig/");  

        // 返回成功信息
        $output->writeln('Generated Successfully!');
    }

    /* 同步的修改api文档
     *
     * @return void
     */
    public function modifyApiMd($filePath, $assigns)
    {
        // 检验api文档是否存在
        $this->checkFile($filePath);

        // 读取文档模板
        $api = file_get_contents('./Application/Utility/Tpl/RestApi.tpl');

        // 处理模板变量
        // 替换变量
        foreach ($assigns as $k => $v) {
            $waitReplace[] = '{{$' . $k . '}}';
            $replace[] = $v;
        }

        $api = str_replace($waitReplace, $replace, $api);
        // 插入最新接口文档
        file_put_contents($filePath, $api, FILE_APPEND);
    }

    /**
     * 检查api文档是否存在 不存在则套用模板创建api文档
     *
     * @param [type] $filePath
     * @return void
     */
    public function checkFile($filePath)
    {
        if (!is_file($filePath)) {
            $baseApi = file_get_contents(__DIR__ . '/Application/Utility/Tpl/BaseApi.tpl');
            file_put_contents($filePath, $baseApi);
        }
    }

    public function restQuery($path, $assigns, $params, $output)
    {
        $path = 'http://' . $this->domain . '/' . $path;
        $curl = new Curl();
        $curl->setJsonDecoder(false);
        // Post Add
        $curl->post($path, $params);
        if ($curl->error) {
            var_dump('url:' . $path);
            var_dump($params);
            $output->writeln('Post data to api failed. Please check the web server!');die;
        } else {
            // 美化json
            $res = json_decode($curl->response, true);
            $resJson = json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
            $assigns['AddRes'] = $resJson;
        }

        // Get List
        $curl->get($path);
        if ($curl->error) {
            $output->writeln('Get dataList from api failed. Please check the web server!');die;
        } else {
            // 美化json
            $res = json_decode($curl->response, true);
            if ($res['code'] == 200 and count($res['data']['list']) >= 1) {
                $id = $res['data']['list'][0]['id'];
                $assigns['ListRes'] = json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
            } else {
                var_dump('url:' . $path);
                var_dump($params);
                $output->writeln('Get dataList from api failed. Please check the web server!');die;
            }
        }

        // PUT Ddit
        foreach ($params as $k => $v) {
            if (is_string($params[$k])) {
                $params[$k] = $params[$k] . " modified";
            }
            if (is_int($params[$k])) {
                $params[$k] = $params[$k] + 1;
            }
        }
        $curl->put($path . "/" . $id, $params);
        if ($curl->error) {
            $output->writeln('Put data to api failed. Please check the web server!');die;
        } else {
            // 美化json
            $res = json_decode($curl->response);
            $resJson = json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
            // p($resJson);
            $assigns['EditRes'] = $resJson;
        }

        // Get Index
        $curl->get($path . "/" . $id);
        if ($curl->error) {
            $output->writeln('Get one items from api failed. Please check the web server!');die;
        } else {
            // 美化json
            $res = json_decode($curl->response);
            $assigns['IndexRes'] = json_encode($res, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        }

        return $assigns;
    }

    /**
     * 自动生成路由
     *
     * @return void
     */
    public function genRoutes($args)
    {
        $route = file_get_contents(__DIR__ . '/../../config/route_client.php');
        $regex = "/'__rest__'(.*?)=>(.*?)\[.+\],/Uis";
        preg_match($regex, $route, $matches);
        $strMatches = $matches[0];
        $moduleName = $args['moduleName'];
        $className = $args['className'];
        // 检查该路由是否已经存在
        $count = substr_count($strMatches, "{$moduleName}/{$className}");

        if ($count != 2) {
            $strMatches = substr_replace($strMatches, "'{$moduleName}/{$className}'								=>'{$moduleName}/{$className}',
        ],", -2);
            $res = preg_replace($regex, $strMatches, $route);

            file_put_contents(__DIR__ . '/../../config/route_client.php', $res);
        }
    }
}
